package ru.dc.object.commands;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <pre>
 * User: Penkov Vladimir
 * Date: 08.10.2010
 * Time: 16:18:40
 * </pre>
 */
public class CommandFactory {

    private List<Class<? extends Command>> registeredCommands = new ArrayList<Class<? extends Command>>();
    private Map<String, Class<? extends Command>> commands;
    private Log logger = LogFactory.getLog(getClass());
    private static CommandFactory instance;

    private CommandFactory() {
        registeredCommands.add(ConnectToMe.class);
        registeredCommands.add(Get.class);
        registeredCommands.add(Direction.class);
        registeredCommands.add(FileLength.class);
        registeredCommands.add(GetNickList.class);
        registeredCommands.add(Hello.class);
        registeredCommands.add(HubName.class);
        registeredCommands.add(HubTopic.class);
        registeredCommands.add(Key.class);
        registeredCommands.add(Lock.class);
        registeredCommands.add(MyINFO.class);
        registeredCommands.add(MyNick.class);
        registeredCommands.add(NickList.class);
        registeredCommands.add(Quit.class);
        registeredCommands.add(RevConnectToMe.class);
        registeredCommands.add(Search.class);
        registeredCommands.add(SR.class);
        registeredCommands.add(Supports.class);
        registeredCommands.add(To.class);
        registeredCommands.add(UserIP.class);
        registeredCommands.add(ValidateNick.class);
        registeredCommands.add(Version.class);

        commands = new HashMap<String, Class<? extends Command>>(registeredCommands.size());

        for (Class<? extends Command> cmdCl : registeredCommands) {
            Command cmd = null;
            try {
                cmd = cmdCl.newInstance();
                commands.put(cmd.getActualCommandName(), cmdCl);
            } catch (Exception e) {
                logger.error("Can't register command for class: "+cmdCl, e);
            }
        }
    }




    public Command createCommand(String commandStr) {

        Command command;
        if (commandStr.startsWith("<")) {
            command = new ChatCommand();
        }
        else {
            //пробел отделяет команду от параметров
            int index = commandStr.indexOf(" ");
            //если пробела нет, значит вся строка - название команды
            if (index<0) {
                index = commandStr.length();
            }
            String cmdName = commandStr.substring(0, index);
            logger.trace("Extracted cmd name: "+cmdName);
            Class<? extends Command> cmdCl = commands.get(cmdName);
            if (cmdCl == null) {
                cmdCl = Command.class;
            }
            logger.trace("Created cmd of class: "+cmdCl.getName());

            try {
                command = cmdCl.newInstance();
            } catch (InstantiationException e) {
                logger.error("Can't create command for class: "+cmdCl, e);
                final Command command1 = new Command();
                command1.setCommand(commandStr);
                return command1;
            } catch (IllegalAccessException e) {
                logger.error("Can't create command for class: "+cmdCl, e);
                final Command command1 = new Command();
                command1.setCommand(commandStr);
                return command1;
            }

        }

        command.setCommand(commandStr);
/*
        try {
            command.parseCommand();
        } catch (Exception e) {
            logger.error("Can't parse command: "+commandStr, e);
        }
*/

        return command;
    }

    public static CommandFactory getInstance() {
        if (instance==null) {
            instance = new CommandFactory();
        }
        return instance;
    }

}
